#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
'''
Created on 16/08/2013

@author: Jesper
'''
import imaplib
import time

_submoduleListForVersioning = []
import versioning; _revisionInfo = versioning.getRevisionInfoFromTagsAndSubModules('$Revision: 124 $', '$Date: 2013-08-25 02:33:57 +0000 (Sun, 25 Aug 2013) $', _submoduleListForVersioning)

SOCKET_TIMEOUT_SECONDS = 60 # timeout in seconds for socket operations

class MyIMAP4_SSL(imaplib.IMAP4_SSL):
    '''
    Hack for bad implementation of sock._recv() under Windows, as well as
    functionality expansion.
    '''
    
    def open(self, *args, **kwargs):
        imaplib.IMAP4_SSL.open(self, *args, **kwargs)
        self.sock.settimeout(SOCKET_TIMEOUT_SECONDS)
        self._secondsSinceTheEpochBefore = time.time()

    def setNotifier(self, notifier):
        self.notifier = notifier

    def _notifySpeed(self, secondsSinceTheEpochBefore, secondsSinceTheEpochAfter, numberOfBytes):
        if hasattr(self, 'notifier'):
            timeDifferenceSeconds = secondsSinceTheEpochAfter - secondsSinceTheEpochBefore
            self.notifier.notifySpeed(numberOfBytes, timeDifferenceSeconds)

    def read(self, numberOfBytes):
        maximumNumberOfBytesPerPart = 32 * 1024  # Read up to 32 Kbytes at a time.
        arrayOfParts = []  # Array of strings, each consisting of a part of the downloaded data. Each part is at most maximumNumberOfBytesPerPart bytes.
        remainingBytes = numberOfBytes
        while remainingBytes > 0:
            numberOfBytesToRead = min(remainingBytes, maximumNumberOfBytesPerPart)
            part = imaplib.IMAP4_SSL.read(self, numberOfBytesToRead)  # Call the implementation from the super class.
            secondsSinceTheEpochAfter = time.time()
            arrayOfParts.append(part)
            sizeOfPartInBytes = len(part)
            assert sizeOfPartInBytes == numberOfBytesToRead 
            self._notifySpeed(self._secondsSinceTheEpochBefore, secondsSinceTheEpochAfter, sizeOfPartInBytes)
            self._secondsSinceTheEpochBefore = secondsSinceTheEpochAfter
            remainingBytes -= sizeOfPartInBytes

        assert remainingBytes == 0
        totalDataRead = ''.join(arrayOfParts)
        assert len(totalDataRead) == numberOfBytes

        return totalDataRead

    def send(self, dataToSend):
        maximumNumberOfBytesPerPart = 32 * 1024  # Send up to 32 Kbytes at a time.
        startIndexForNextBlock = 0
        while startIndexForNextBlock < len(dataToSend):
            part = dataToSend[startIndexForNextBlock:startIndexForNextBlock+maximumNumberOfBytesPerPart]
            imaplib.IMAP4_SSL.send(self, part)  # Call the implementation from the super class.
            secondsSinceTheEpochAfter = time.time()
            sizeOfPartInBytes = len(part)
            self._notifySpeed(self._secondsSinceTheEpochBefore, secondsSinceTheEpochAfter, sizeOfPartInBytes)
            self._secondsSinceTheEpochBefore = secondsSinceTheEpochAfter
            startIndexForNextBlock += sizeOfPartInBytes
 
        assert startIndexForNextBlock == len(dataToSend)
